﻿using System;
using System.IO;
using System.Net.Mail;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Xml.Linq;

namespace TireService.Data
{
    /// <summary>
    /// Summary description for Shared
    /// </summary>
    public class Shared
    {
        #region Shared Properties

        public enum EconomicInterfaceObjects
        { 
            Debtor = 10,
            CustomerSubscription = 20,
            Invoice = 30
        }

        public enum EconomicInterfaceActions
        { 
            CreateObject = 10,
            UpdateObject = 20,
            BookInvoice = 30,
            MarkInvoiceAsPaid = 40,
        }

        public enum EcoCashBooks
        {
            Daily = 1,
            Payments = 2,
            Salary = 3
        }

        public enum SubscriptionRenewalMethod
        { 
            InvoicePBS = 1,
            InvoiceEmail = 2,
            InvoiceManual = 3
        }

        public enum SubscriptionLogAction
        {
            Created = 10,
            Edited = 20,
            DeActivated = 30,
            ReActivated = 40,
            Paid = 50,
            SubscriptionChanged = 60,
            Renewal = 70
        };

        public enum CarStatus
        {
            Active = 10,
            InActive = 20,
            NeedsTireChanged = 30,
            AwaitsTireChangePlanning = 35,
            TireChanged = 40,
            PlannedTireChange = 50
            //TireMeasured = 55,
            //NeedsTirePickedUp = 60,
            //PlannedTirePickUp = 70,
            //NeedsTireReturned = 80,
            //PlannedTireReturn = 90,
            //TireReturned = 100
        };

        public enum TireSetStatus
        {
            MountedOnCar = 1,
            OnStock = 2,
            InActive = 3,
            PlacedAtCustomer = 4,
            PackedForService = 5,
            StockedAtCustomer = 6,
            ReturnedToCustomer = 7,
            AwaitsMoveToStock = 8
        };

        public enum ServiceTaskStatus
        {
            Planned = 1,
            Completed = 2,
            Cancelled = 3,
            NotPossibleToExecute = 4
        };

        public enum ScheduleDetailType
        {
            TireChange = 0, //Updated: 2012-09-10: Skal udfases når systemets data er klar til dette
            ServiceDrive = 1,
            Available = 2,
            Blocked = 3
        };

        public enum TireType
        {
            AllYearTires = 1,
            SummerTires = 2,
            WinterTires = 3
        };

        //public enum InvoiceStatus
        //{
        //    Invoiced = 1,
        //    Reminder = 2,
        //    ReminderFeeOne = 3,
        //    ReminderFeeTwo = 4,
        //    ReminderFeeThree = 5,
        //    CreditCollection = 6,
        //    Paid = 7,
        //    Cancelled = 8
        //};

        public enum Currency
        {
            DKK = 1
        };

        public enum TaskType
        { 
            ServiceDrive = 1,
            StockTask = 2,
            BackofficeTask = 3,
            StockMove = 4
        };

        public enum TaskDetailType
        {
            ServiceDrive_PickUpTire = 1,
            ServiceDrive_ChangeTire = 2,
            ServiceDrive_ReturnTire = 3,
            StockTask_RepairTire = 4,
            StockTask_BalanceWheel = 5,
            StockTask_MountNewTire = 6,
            StockTask_RemoveOldTire = 7,
            StockTask_HandoutTireSet = 8,
            StockTask_DiscardTireSet = 9,
            StockTask_MeasureTirePattern = 10,
            StockMove_MoveTireSetToNewContainer = 11,
            StockMove_MoveTireSetToNewCargoRoom = 12
        };

        public enum TaskTypeStatus
        {
            ServiceDrive_Created = 1,
            ServiceDrive_Planned = 2,
            ServiceDrive_Completed = 3,
            ServiceDrive_Replan = 4,
            ServiceDrive_Cancelled = 5,
            StockTask_Created = 6,
            StockTask_Completed = 7,
            StockTask_Cancelled = 8
        };

        public enum PaymentGateWayActions
        {
            PaymentFailed = 0,
            PaymentCompleted = 1,
            InitiatePayment = 2
        }

        public enum ScheduledJobId
        {
            WebshopOrderInterface = 1,
            CustomerServiceReminder = 2,
            BenifyOrderInterface = 3,
            TestJob = 4,
            CreateBenifyOrders = 5
        }

        #endregion

        #region Shared Functions



        /// <summary>
        /// Function that return monthname in correct language based on datevalue
        /// </summary>
        /// <param name="dateValue">Date</param>
        /// <returns>String with month name in right culture</returns>
        public static string GetMonthName(DateTime dateValue)
        {
          DateTimeFormatInfo info = new DateTimeFormatInfo();
          string[] names;

          names = info.MonthNames;

          return names[dateValue.Month - 1];
        }

        /// <summary>
        /// Function that return monthname in correct language based on month number
        /// </summary>
        /// <param name="MonthNumber">Integer with month number (1-12)</param>
        /// <returns>String with month name in right culture</returns>
        public static string GetMonthName(int MonthNumber)
        {
            DateTime date = new DateTime(1900, MonthNumber, 1);

            return GetMonthName(date);
        }

        //public static double[] GetLongLatCoordinates(string Address, string MapKey)
        //{
        //    GMapGeocoder.Containers.Results coordinatesSecondary = new GMapGeocoder.Containers.Results();
        //    coordinatesSecondary = GMapGeocoder.Util.Geocode(Address, MapKey);
        //    double[] LongLatCoordinates = new double[] { };
        //    LongLatCoordinates[0] = (double)coordinatesSecondary.Addresses[0].Coordinates.Longitude / 10000000;
        //    LongLatCoordinates[1] = (double)coordinatesSecondary.Addresses[0].Coordinates.Latitude / 10000000;

        //    return LongLatCoordinates;
        //}

        /// <summary>
        /// Function that sends email
        /// </summary>
        /// <param name="ToAddress">Address of the reciever</param>
        /// <param name="FromAddress">Address of the sender</param>
        /// <param name="Message">Email message</param>
        /// <param name="Subject">Email subject</param>
        /// <param name="IsBodyHtml">True/False value indicating if email is in HTML format</param>
        public void SendEmail(string ToAddress, string FromAddress, string Message, string Subject, bool IsBodyHtml, bool TestEnvironmentOn, string BccAddress, Stream attachment, string Filename, int? CustomerId, Guid UserId)
        {
            //if (attachment != null | Filename != null)
            //{
            //    SendEmail(ToAddress, FromAddress, Message, Subject, IsBodyHtml, TestEnvironmentOn, BccAddress, null, null);
            //}
            //else
            //{
            //    SendEmail(ToAddress, FromAddress, Message, Subject, IsBodyHtml, TestEnvironmentOn, BccAddress, attachment, Filename);
            //}

            SendEmail(ToAddress, FromAddress, Message, Subject, IsBodyHtml, TestEnvironmentOn, BccAddress, attachment, Filename);
            
            // Create customer mail log, if mail is for customer
            if (CustomerId != null)
	        {
		        TireServiceDB db = new TireServiceDB();

                CustomerMailLog maillog = new CustomerMailLog();
                maillog.CustomerId = Convert.ToInt32(CustomerId);
                maillog.UserId = UserId;
                maillog.Subject = Subject;
                maillog.Message = Message;
                maillog.SendDate = DateTime.Now;
                maillog.FromEmail = FromAddress;
                maillog.ToEmail = ToAddress;

                db.CustomerMailLogs.InsertOnSubmit(maillog);

                db.SubmitChanges();

                db.Dispose();
	        }
        }

        /// <summary>
        /// Function that sends email
        /// </summary>
        /// <param name="ToAddress">Address of the reciever</param>
        /// <param name="FromAddress">Address of the sender</param>
        /// <param name="Message">Email message</param>
        /// <param name="Subject">Email subject</param>
        /// <param name="IsBodyHtml">True/False value indicating if email is in HTML format</param>
        public void SendEmail(string ToAddress, string FromAddress, string Message, string Subject, bool IsBodyHtml, bool TestEnvironmentOn, string BccAddress, Stream attachment, string Filename)
        {
            if (TestEnvironmentOn)
            {
                // Only testing - send to test mail
                //(1) Create the MailMessage instance 
                MailMessage mm = new MailMessage(FromAddress, "jannik@mobilhjulskift.dk");

                //(2) Assign the MailMessage's properties 
                mm.Subject = Subject;
                mm.Body = "TEST SYSTEM " + Message;
                mm.IsBodyHtml = IsBodyHtml;                

                //(2b) Attach file
                if (attachment != null)
	            {
                    mm.Attachments.Add(new Attachment(attachment, Filename));
	            }
                
                //(3) Create the SmtpClient object 
                SmtpClient smtp = new SmtpClient();
                smtp.EnableSsl = true;

                //(4) Send the MailMessage (will use the Web.config settings) 
                smtp.Send(mm);

                smtp.Dispose();
            }
            else
            {
                //(1) Create the MailMessage instance 
                MailMessage mm = new MailMessage(FromAddress, ToAddress);

                //(2) Assign the MailMessage's properties 
                mm.Subject = Subject;
                mm.Body = Message;
                mm.IsBodyHtml = IsBodyHtml;
                
                if (BccAddress != null)
                {
                    mm.Bcc.Add(BccAddress.ToString());
                }

                //(2b) Attach file
                if (attachment != null)
                {
                    mm.Attachments.Add(new Attachment(attachment, Filename));
                }

                //(3) Create the SmtpClient object 
                SmtpClient smtp = new SmtpClient();
                smtp.EnableSsl = true;
                
                //(4) Send the MailMessage (will use the Web.config settings) 
                smtp.Send(mm);

                smtp.Dispose();
            }
        }

        /// <summary>
        /// Creates a resized bitmap from an existing image on disk
        /// </summary>
        /// <param name="SourceFilename">Path and filename on source to create a thumb</param>
        /// <param name="Width">Width for thumb</param>
        /// <param name="Height">Height for thumb</param>
        /// <param name="PixFormat">Set pix depth on new bitmap</param>
        /// <returns>Bitmap object with thumb</returns>
        public static Bitmap CreateThumbnail(string SourceFilename, int Width, int Height, PixelFormat PixFormat)
        {
            System.Drawing.Bitmap bmOut = null;
            try
            {
                Bitmap bmOriginal = new Bitmap(SourceFilename);
                ImageFormat loFormat = bmOriginal.RawFormat;

                decimal Ratio;
                int NewWidth = 0;
                int NewHeight = 0;

                if (bmOriginal.Width < Width && bmOriginal.Height < Height)
                    return bmOriginal;

                if (bmOriginal.Width > bmOriginal.Height)
                {
                    Ratio = (decimal)Width / bmOriginal.Width;
                    NewWidth = Width;
                    decimal lnTemp = bmOriginal.Height * Ratio;
                    NewHeight = (int)lnTemp;
                }
                else
                {
                    Ratio = (decimal)Height / bmOriginal.Height;
                    NewHeight = Height;
                    decimal lnTemp = bmOriginal.Width * Ratio;
                    NewWidth = (int)lnTemp;
                }

                bmOut = new Bitmap(NewWidth, NewHeight, PixFormat);
                //bmOut.SetResolution(96, 96);
                Graphics g = Graphics.FromImage(bmOut);

                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

                g.FillRectangle(Brushes.White, 0, 0, NewWidth, NewHeight);
                g.DrawImage(bmOriginal, 0, 0, NewWidth, NewHeight);

                g.Dispose();
                bmOriginal.Dispose();
            }
            catch
            {
                return null;
            }

            return bmOut;
        }

        /// <summary>
        /// This function is used to get the imageCode info
        /// on the basis of mimeType
        /// </summary>
        /// <param name="mimeType">string data type</param>
        /// <returns>ImageCodecInfo data type</returns>
        public static ImageCodecInfo GetImageCoeInfo(string mimeType)
        {
            ImageCodecInfo[] codes = ImageCodecInfo.GetImageEncoders();
            for (int i = 0; i < codes.Length; i++)
            {
                if (codes[i].MimeType == mimeType)
                {
                    return codes[i];
                }
            }
            return null;
        }

        /// <summary>
        /// Method for cropping an image.
        /// </summary>
        /// <param name="img">the image to crop</param>
        /// <param name="width">new height</param>
        /// <param name="height">new width</param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static Image CropImage(string img, int width, int height, int x, int y)
        {
            try
            {
                Image image = Image.FromFile(img);
                Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
                bmp.SetResolution(80, 60);

                Graphics gfx = Graphics.FromImage(bmp);
                gfx.SmoothingMode = SmoothingMode.AntiAlias;
                gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
                gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;
                gfx.DrawImage(image, new Rectangle(0, 0, width, height), x, y, width, height, GraphicsUnit.Pixel);
                // Dispose to free up resources
                image.Dispose();
                bmp.Dispose();
                gfx.Dispose();

                return bmp;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// Function that copies all files in a specific folder to another folder
        /// </summary>
        /// <param name="sourcePath">String with path to sourcefiles</param>
        /// <param name="destPath">String with path to destination folder</param>
        /// <param name="overwrite">True/false to indicate if files is alloved to be overwritten</param>
        public void CopyFiles(string sourcePath, string destPath, bool overwrite)
        {
            System.IO.DirectoryInfo sourceDir = new System.IO.DirectoryInfo(sourcePath);
            System.IO.DirectoryInfo destDir = new System.IO.DirectoryInfo(destPath);

            // The source directory must exist for our code to run
            if (sourceDir.Exists)
            {
                // If the destination folder does not exist, create it
                if (!destDir.Exists)
                {
                    destDir.Create();
                }
                // Loop through all the files of the current directory and copy them if overwrite=true or they do not exist
                foreach (System.IO.FileInfo file in sourceDir.GetFiles())
                {
                    if (overwrite)
                    {
                        file.CopyTo(System.IO.Path.Combine(destDir.FullName, file.Name), true);
                    }
                    else
                    {
                        if (System.IO.File.Exists(System.IO.Path.Combine(destDir.FullName, file.Name)) == false)
                        {
                            file.CopyTo(System.IO.Path.Combine(destDir.FullName, file.Name), false);
                        }
                    }
                }
            }
            else
            {
                // If source directory does not exist
            }
        }

        /// <summary>
        /// Function that copies a directory including subfolders and files
        /// </summary>
        /// <param name="sourcePath">String with path to source folder</param>
        /// <param name="destPath">String with path to destination folder</param>
        /// <param name="overwrite">True/false to indicate if files is alloved to be overwritten</param>
        public void CopyDirectory(string sourcePath, string destPath, bool overwrite)
        {
            System.IO.DirectoryInfo sourceDir = new System.IO.DirectoryInfo(sourcePath);
            System.IO.DirectoryInfo destDir = new System.IO.DirectoryInfo(destPath);
            
            // The source directory must exist for our code to run
            if (sourceDir.Exists)
	        {
                // If the destination folder does not exist, create it
        	    if (!destDir.Exists)
	            {
            		 destDir.Create();
	            }	 
                // Loop through all the files of the current directory and copy them if overwrite=true or they do not exist
                foreach (System.IO.FileInfo file in sourceDir.GetFiles())
	            {
            	    if (overwrite)
	                {
		                 file.CopyTo(System.IO.Path.Combine(destDir.FullName, file.Name), true);
                    }
                    else
                    {
                        if (System.IO.File.Exists(System.IO.Path.Combine(destDir.FullName, file.Name)) == false)
                        {
                            file.CopyTo(System.IO.Path.Combine(destDir.FullName, file.Name), false);
                        }
                    }    	 
	            }

                // Loop through all the subfolders and call this method recursively
                foreach (System.IO.DirectoryInfo dir in sourceDir.GetDirectories())
                {
                    CopyDirectory(dir.FullName, System.IO.Path.Combine(destDir.FullName, dir.Name), overwrite);
                }
            }
            else
            {
                // If source directory does not exist
            }    
        }

        #endregion

        #region Shared Classes

        


        /// <remarks>
        /// Template Parser is simple parser has been written on C#.
        /// It allows setup variables and conditions block in template.
        /// Also you can use some of variable's modificators.
        ///
        ///     Author: Alexander Kleshevnikov
        ///     E-mail: seigo@icconline.com
        ///
        /// <example>There is the simpl example of template for html page:
        /// <code>
        /// <html>
        /// <head><title>##Title##</title></head>
        /// <body><h1>##Title:upper##</h1>
        /// ##If--IsRegisteredUser##
        /// Hello, ##UserName##!
        /// ##Else--IsRegisteredUser##
        /// Please sign in.
        /// ##EndIf--IsRegisteredUser##
        /// </body>
        /// </html>
        /// </code>
        /// To parse this template you can use the following code:
        /// <code>
        /// ...
        /// Hashtable Variables = new Hashtable();
        /// Variables.Add("Title", "Login In");
        /// Variables.Add("IsRegisteredUser", true);
        /// Variables.Add("UserName", "seigo");
        /// TemplateParser tpl = new TemplateParser("template.htm", Variables);
        /// tpl.ParseToFile("result.htm");
        /// ...
        /// </code>
        /// </example>
        /// </remarks>
        public class Parser
        {
            private string _strTemplateBlock;
            private Hashtable _hstValues;
            private Hashtable _ErrorMessage = new Hashtable();
            private string _ParsedBlock;

            private Dictionary<string, Parser> _Blocks = new Dictionary<string, Parser>();

            private string VariableTagBegin = "##";
            private string VariableTagEnd = "##";

            private string ModificatorTag = ":";
            private string ModificatorParamSep = ",";

            private string ConditionTagIfBegin = "##If--";
            private string ConditionTagIfEnd = "##";
            private string ConditionTagElseBegin = "##Else--";
            private string ConditionTagElseEnd = "##";
            private string ConditionTagEndIfBegin = "##EndIf--";
            private string ConditionTagEndIfEnd = "##";

            private string BlockTagBeginBegin = "##BlockBegin--";
            private string BlockTagBeginEnd = "##";
            private string BlockTagEndBegin = "##BlockEnd--";
            private string BlockTagEndEnd = "##";

            /// <value>Template block</value>
            public string TemplateBlock
            {
                get { return this._strTemplateBlock; }
                set
                {
                    this._strTemplateBlock = value;
                    ParseBlocks();
                }
            }

            /// <value>Template Variables</value>
            public Hashtable Variables
            {
                get { return this._hstValues; }
                set { this._hstValues = value; }
            }

            /// <value>Error Massage</value>
            public Hashtable ErrorMessage
            {
                get { return _ErrorMessage; }
            }

            /// <value>Blocks inside template</value>
            public Dictionary<string, Parser> Blocks
            {
                get { return _Blocks; }
            }

            /// <summary>
            /// Creates a new instance of TemplateParser
            /// </summary>

            #region Contructors
            public Parser()
            {
                this._strTemplateBlock = "";
            }

            public Parser(string FilePath)
            {
                ReadTemplateFromFile(FilePath);
                ParseBlocks();
            }

            public Parser(Hashtable Variables)
            {
                this._hstValues = Variables;
            }

            public Parser(string FilePath, Hashtable Variables)
            {
                ReadTemplateFromFile(FilePath);
                this._hstValues = Variables;
                ParseBlocks();
            }

            public Parser(string FileContent, Hashtable Variables, bool FileContentHTML)
            {
                this.TemplateBlock = FileContent;
                this._hstValues = Variables;
                ParseBlocks();
            }

            #endregion

            /// <summary>
            /// Setup template from specified file
            /// </summary>
            /// <param name="FilePath">Full phisical path to template file</param>
            public void SetTemplateFromFile(string FilePath)
            {
                ReadTemplateFromFile(FilePath);
            }

            /// <summary>
            /// Setup template as string block
            /// </summary>
            /// <param name="TemplateBlock">String template block</param>
            public void SetTemplate(string TemplateBlock)
            {
                this.TemplateBlock = TemplateBlock;
            }

            /// <summary>
            /// Parse template after setuping Template and Variables
            /// </summary>
            /// <returns>
            /// Parsed Block for Whole Template
            /// </returns>
            public string Parse()
            {
                ParseConditions();
                ParseVariables();
                return this._ParsedBlock;
            }

            /// <summary>
            /// Parse Template Block
            /// </summary>
            /// <returns>
            /// Parsed Block for Specified BlockName
            /// </returns>
            public string ParseBlock(string BlockName, Hashtable Variables)
            {
                if (!this._Blocks.ContainsKey(BlockName))
                {
                    throw new ArgumentException(String.Format("Could not find Block with Name '{0}'", BlockName));
                }

                this._Blocks[BlockName].Variables = Variables;
                return this._Blocks[BlockName].Parse();
            }

            /// <summary>
            /// Parse template and save result into specified file
            /// </summary>
            /// <param name="FilePath">Full physical path to file</param>
            /// <param name="ReplaceIfExists">If true file which already exists
            /// will be replaced</param>
            /// <returns>True if new content has been written</returns>
            public bool ParseToFile(string FilePath, bool ReplaceIfExists)
            {
                if (File.Exists(FilePath) && !ReplaceIfExists)
                {
                    return false;
                }
                else
                {
                    StreamWriter sr = File.CreateText(FilePath);
                    sr.Write(Parse());
                    sr.Close();
                    return true;
                }
            }

            /// <summary>
            /// Read template content from specified file
            /// </summary>
            /// <param name="FilePath">Full physical path to template file</param>
            private void ReadTemplateFromFile(string FilePath)
            {
                if (!File.Exists(FilePath))
                {
                    throw new ArgumentException("Template file does not exist.");
                }

                StreamReader reader = new StreamReader(FilePath);
                this.TemplateBlock = reader.ReadToEnd();
                reader.Close();
            }

            /// <summary>
            /// Parse all blocks in template
            /// </summary>
            private void ParseBlocks()
            {
                //int idxPrevious = 0;
                int idxCurrent = 0;
                while ((idxCurrent = this._strTemplateBlock.IndexOf(this.BlockTagBeginBegin, idxCurrent)) != -1)
                {
                    string BlockName;
                    int idxBlockBeginBegin, idxBlockBeginEnd, idxBlockEndBegin;

                    idxBlockBeginBegin = idxCurrent;
                    idxCurrent += this.BlockTagBeginBegin.Length;

                    // Searching for BlockBeginEnd Index

                    idxBlockBeginEnd = this._strTemplateBlock.IndexOf(this.BlockTagBeginEnd, idxCurrent);
                    if (idxBlockBeginEnd == -1) throw new Exception("Could not find BlockTagBeginEnd");

                    // Getting Block Name

                    BlockName = this._strTemplateBlock.Substring(idxCurrent, (idxBlockBeginEnd - idxCurrent));
                    idxCurrent = idxBlockBeginEnd + this.BlockTagBeginEnd.Length;

                    // Getting End of Block index

                    string EndBlockStatment = this.BlockTagEndBegin + BlockName + this.BlockTagEndEnd;
                    idxBlockEndBegin = this._strTemplateBlock.IndexOf(EndBlockStatment, idxCurrent);
                    if (idxBlockEndBegin == -1) throw new Exception("Could not find End of Block with name '" + BlockName + "'");

                    // Add Block to Dictionary

                    Parser block = new Parser();
                    block.TemplateBlock = this._strTemplateBlock.Substring(idxCurrent, (idxBlockEndBegin - idxCurrent));
                    this._Blocks.Add(BlockName, block);

                    // Remove Block Declaration From Template

                    this._strTemplateBlock = this._strTemplateBlock.Remove(idxBlockBeginBegin, (idxBlockEndBegin - idxBlockBeginBegin));

                    idxCurrent = idxBlockBeginBegin;
                }
            }

            /// <summary>
            /// Parse all conditions in template
            /// </summary>
            private void ParseConditions()
            {
                int idxPrevious = 0;
                int idxCurrent = 0;
                this._ParsedBlock = "";
                while ((idxCurrent = this._strTemplateBlock.IndexOf(this.ConditionTagIfBegin, idxCurrent)) != -1)
                {
                    string VarName;
                    string TrueBlock, FalseBlock;
                    string ElseStatment, EndIfStatment;
                    int idxIfBegin, idxIfEnd, idxElseBegin, idxEndIfBegin;
                    bool boolValue;

                    idxIfBegin = idxCurrent;
                    idxCurrent += this.ConditionTagIfBegin.Length;

                    // Searching for EndIf Index

                    idxIfEnd = this._strTemplateBlock.IndexOf(this.ConditionTagIfEnd, idxCurrent);
                    if (idxIfEnd == -1) throw new Exception("Could not find ConditionTagIfEnd");

                    // Getting Value Name

                    VarName = this._strTemplateBlock.Substring(idxCurrent, (idxIfEnd - idxCurrent));

                    idxCurrent = idxIfEnd + this.ConditionTagIfEnd.Length;

                    // Compare ElseIf and EndIf Indexes

                    ElseStatment = this.ConditionTagElseBegin + VarName + this.ConditionTagElseEnd;
                    EndIfStatment = this.ConditionTagEndIfBegin + VarName + this.ConditionTagEndIfEnd;
                    idxElseBegin = this._strTemplateBlock.IndexOf(ElseStatment, idxCurrent);
                    idxEndIfBegin = this._strTemplateBlock.IndexOf(EndIfStatment, idxCurrent);
                    if (idxElseBegin > idxEndIfBegin) throw new Exception("Condition Else Tag placed after Condition Tag EndIf for '" + VarName + "'");

                    // Getting True and False Condition Blocks

                    if (idxElseBegin != -1)
                    {
                        TrueBlock = this._strTemplateBlock.Substring(idxCurrent, (idxElseBegin - idxCurrent));
                        FalseBlock = this._strTemplateBlock.Substring((idxElseBegin + ElseStatment.Length), (idxEndIfBegin - idxElseBegin - ElseStatment.Length));
                    }
                    else
                    {
                        TrueBlock = this._strTemplateBlock.Substring(idxCurrent, (idxEndIfBegin - idxCurrent));
                        FalseBlock = "";
                    }

                    // Parse Condition

                    try
                    {
                        boolValue = Convert.ToBoolean(this._hstValues[VarName]);
                    }
                    catch
                    {
                        boolValue = false;
                    }

                    string BeforeBlock = this._strTemplateBlock.Substring(idxPrevious, (idxIfBegin - idxPrevious));

                    if (this._hstValues.ContainsKey(VarName) && boolValue)
                    {
                        this._ParsedBlock += BeforeBlock + TrueBlock.Trim();
                    }
                    else
                    {
                        this._ParsedBlock += BeforeBlock + FalseBlock.Trim();
                    }

                    idxCurrent = idxEndIfBegin + EndIfStatment.Length;
                    idxPrevious = idxCurrent;
                }
                this._ParsedBlock += this._strTemplateBlock.Substring(idxPrevious);
            }

            /// <summary>
            /// Parse all variables in template
            /// </summary>
            private void ParseVariables()
            {
                int idxCurrent = 0;
                while ((idxCurrent = this._ParsedBlock.IndexOf(this.VariableTagBegin, idxCurrent)) != -1)
                {
                    string VarName, VarValue;
                    int idxVarTagEnd;

                    idxVarTagEnd = this._ParsedBlock.IndexOf(this.VariableTagEnd, (idxCurrent + this.VariableTagBegin.Length));
                    if (idxVarTagEnd == -1) throw new Exception(String.Format("Index {0}: could not find Variable End Tag", idxCurrent));

                    // Getting Variable Name

                    VarName = this._ParsedBlock.Substring((idxCurrent + this.VariableTagBegin.Length), (idxVarTagEnd - idxCurrent - this.VariableTagBegin.Length));

                    // Checking for Modificators

                    string[] VarParts = VarName.Split(this.ModificatorTag.ToCharArray());
                    VarName = VarParts[0];

                    // Getting Variable Value
                    // If Variable doesn't exist in _hstValue then
                    // Variable Value equal empty string

                    // [added 6/6/2006] If variable is null than it will also has empty string

                    VarValue = String.Empty;
                    if (this._hstValues.ContainsKey(VarName) && this._hstValues[VarName] != null)
                    {
                        VarValue = this._hstValues[VarName].ToString();
                    }

                    // Apply All Modificators to Variable Value

                    for (int i = 1; i < VarParts.Length; i++)
                        this.ApplyModificator(ref VarValue, VarParts[i]);

                    // Replace Variable in Template

                    this._ParsedBlock = this._ParsedBlock.Substring(0, idxCurrent) + VarValue + this._ParsedBlock.Substring(idxVarTagEnd + this.VariableTagEnd.Length);

                    // Add Length of added value to Current index 
                    // to prevent looking for variables in the added value
                    // Fixed Date: April 5, 2006
                    idxCurrent += VarValue.Length;
                }
            }

            /// <summary>
            /// Method for applying modificators to variable value
            /// </summary>
            /// <param name="Value">Variable value</param>
            /// <param name="Modificator">Determination statment</param>
            private void ApplyModificator(ref string Value, string Modificator)
            {
                // Checking for parameters

                string strModificatorName = "";
                string strParameters = "";
                int idxStartBrackets, idxEndBrackets;
                if ((idxStartBrackets = Modificator.IndexOf("(")) != -1)
                {
                    idxEndBrackets = Modificator.IndexOf(")", idxStartBrackets);
                    if (idxEndBrackets == -1)
                    {
                        throw new Exception("Incorrect modificator expression");
                    }
                    else
                    {
                        strModificatorName = Modificator.Substring(0, idxStartBrackets).ToUpper();
                        strParameters = Modificator.Substring(idxStartBrackets + 1, (idxEndBrackets - idxStartBrackets - 1));
                    }
                }
                else
                {
                    strModificatorName = Modificator.ToUpper();
                }
                string[] arrParameters = strParameters.Split(this.ModificatorParamSep.ToCharArray());
                for (int i = 0; i < arrParameters.Length; i++)
                    arrParameters[i] = arrParameters[i].Trim();

                try
                {
                    Type typeModificator = Type.GetType("TemplateParser.Modificators." + strModificatorName);
                    if (typeModificator.IsSubclassOf(Type.GetType("TemplateParser.Modificators.Modificator")))
                    {

                        Modificator objModificator = (Modificator)Activator.CreateInstance(typeModificator);
                        objModificator.Apply(ref Value, arrParameters);
                    }
                }
                catch
                {
                    throw new Exception(String.Format("Could not find modificator '{0}'", strModificatorName));
                }
            }
        }

        #endregion

    }
}